package com.yonyou.pmclouds.project.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.PMControllerConst;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.IllegalRequestArgException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.BeanHelper;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.CodeNameUtils;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.enterprise.entity.EnterpriseInfo;
import com.yonyou.pmclouds.enterprise.entity.EnterpriseVO;
import com.yonyou.pmclouds.enterprise.rmiitf.EnterpriseQuery;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationQuery;
import com.yonyou.pmclouds.outter.enterprise.EnterpriseInfoQuery;
import com.yonyou.pmclouds.outter.role.UserRoleInfoQuery;
import com.yonyou.pmclouds.outter.tenant.TenantInfoQuery;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.outter.user.UserOperator;
import com.yonyou.pmclouds.personnel.entity.PersonnelVO;
import com.yonyou.pmclouds.personnel.rmiitf.PersonnelQuery;
import com.yonyou.pmclouds.plan.entity.PlanTempletVO;
import com.yonyou.pmclouds.plan.entity.ProjectPlanVO;
import com.yonyou.pmclouds.plan.rmiitf.PlanTempletService;
import com.yonyou.pmclouds.plan.rmiitf.ProjectPlanMaintain;
import com.yonyou.pmclouds.project.entity.ProjectConst;
import com.yonyou.pmclouds.project.entity.ProjectUpdateViewVO;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.entity.ProjectViewVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectMaintain;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseVO;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseViewVO;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.entity.TeamMemberViewVO;
import com.yonyou.pmclouds.team.rmiitf.ProjectRefWithTeamQuery;
import com.yonyou.pmclouds.tenant.entity.TenantInfo;
import com.yonyou.pmclouds.user.entity.UserInfo;
import com.yonyou.pmclouds.user.entity.UserSearchResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.yonyou.pmclouds.basecom.PMControllerConst.DEFAULT_PAGE_PAGE_START;
import static com.yonyou.pmclouds.basecom.PMControllerConst.DEFAULT_PAGE_SIZE;


@Slf4j
@RestController
@RequestMapping(value = "/project")
public class ProjectController {

    private static final String[] USER_ID_FIELDS = {ProjectVO.MANAGER, ProjectVO.CREATOR};

    private static final String[] USER_NAME_FIELDS = {ProjectVO.MANAGER_NAME, ProjectVO.CREATOR_NAME};

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectSimpleQuery query;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectMaintain maintain;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectPlanMaintain projectPlanMaintain;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private OrganizationQuery organizationQuery;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private PlanTempletService planTempletService;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectRefWithTeamQuery teamQuery;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectRefWithTeamQuery projectRefWithTeamQuery;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private EnterpriseQuery enterpriseQuery;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private PersonnelQuery personnelQuery;

    @Autowired
    private UserInfoQuery userInfoQuery;

    @Autowired
    private EnterpriseInfoQuery enterpriseInfoQuery;

    @Autowired
    private UserOperator userOperator;

    @Autowired
    private TenantInfoQuery tenantInfoQuery;

    @Autowired
    private UserRoleInfoQuery userRoleInfoQuery;

    @Value("${pmcloud.useNewProjectTeamTenant}")
    private String useNewTeamTenantIds;

    @GetMapping(value = "/list")
    public PageObject<ProjectVO> list(@RequestParam(name = "keyword", required = false) String keyword,
                                      @RequestParam(name = "projectState", required = false) String projectState,
                                      @RequestParam(name = "pageStart", required = false, defaultValue = DEFAULT_PAGE_PAGE_START) String pageStart,
                                      @RequestParam(name = "pageSize", required = false, defaultValue = DEFAULT_PAGE_SIZE) String pageSize)
            throws BusinessException {
        Byte state = projectState == null ? null : Byte.parseByte(projectState);
        PageObject<ProjectVO> projectPage = query.queryByManagerOrCreator(RuntimeEnvironment.getLoginUserId(), keyword,
                state, Integer.valueOf(pageStart), Integer.valueOf(pageSize));
        // 组装项目经理
        userInfoQuery.tranUserInfoField(projectPage.getObjects(),
                USER_ID_FIELDS, USER_NAME_FIELDS);
        // 处理组织名称为空的情况
        setOrgName(projectPage.getObjects());

        return projectPage;
    }

    /**
     * 是否使用新版本的项目团队，false继续使用原有接口
     */
    @RequestMapping("/isUseNewTeam")
    public boolean isUseNewTeam() {
        boolean flag = false;
        String tenantId = RuntimeEnvironment.getTenantId();
        if (StringUtils.isNotEmpty(useNewTeamTenantIds) && useNewTeamTenantIds.contains(tenantId)) {
            flag = true;
        }

        return flag;
    }

    @GetMapping(value = "/queryListByProjectName")
    @ResponseBody
    public PageObject<?> queryListByProjectName() throws BusinessException, IOException {
        String userid = RuntimeEnvironment.getLoginUserId();
        String tenantid = RuntimeEnvironment.getTenantId();
        List<String> pkRoles = getRolesByUser(userid, tenantid);
        PageObject<?> projects = teamQuery.queryOfUser(userid, tenantid, null,
                Integer.valueOf(PMControllerConst.DEFAULT_PAGE_PAGE_START), 1000, pkRoles.toArray(new String[0]));
        return projects;
    }

    private List<String> getRolesByUser(String userId, String tenantId) throws IOException {
        Map map = userOperator.queryRoleByUserId(tenantId, userId);
        List<String> pkRoles = new ArrayList<>();
        if (map != null && map.get("data") != null) {
            pkRoles = (ArrayList) map.get("data");
        }
        return pkRoles;
    }

    @GetMapping(value = "/queryProjectsByOrg")
    @ResponseBody
    public ProjectVO[] queryProjectsByOrg(@RequestParam(value = "pkOrg", required = false) String pkOrg) throws BusinessException {
        String pkTenant = RuntimeEnvironment.getTenantId();
        String[] projectIds;
        if (StringUtils.isNotEmpty(pkOrg)) {
            projectIds = query.queryProjectIdsByOrgs(pkTenant, new String[]{pkOrg});
        } else {
            projectIds = query.queryProjectIdByTenantOrg(null, pkTenant, null);
        }

        if (projectIds == null || projectIds.length <= 0) {
            return new ProjectVO[]{};
        }

        return query.queryVOByIds(projectIds);
    }

    /**
     * 单组织查询项目
     *
     * @param pkOrg
     * @return
     * @throws BusinessException
     */
    @GetMapping(value = "/queryProjectsByOrgExt")
    @ResponseBody
    public ProjectVO[] queryProjectsByOrgExt(@RequestParam(value = "pkOrg", required = false) String pkOrg) throws BusinessException {
        String tenantId = RuntimeEnvironment.getTenantId();
        if (StringUtils.isEmpty(pkOrg)) {
            return new ProjectVO[0];
        }
        ProjectVO[] projectIds = new ProjectVO[0];
        if (pkOrg.equals(tenantId)) {
            projectIds = query.queryProjectIdByTenantOrgExt(tenantId, null);
        } else {
            projectIds = query.queryProjectIdByTenantOrgExt(tenantId, pkOrg);
        }
        return projectIds;
    }


    /**
     * 获取用户有权限的组织
     *
     * @return
     */
    private String[] getPermOrgByUser() throws BusinessException {
        String pkTenant = RuntimeEnvironment.getTenantId();
        String pkUser = RuntimeEnvironment.getLoginUserId();
        String[] pkRoles = userRoleInfoQuery.getUserRoles(pkUser, pkTenant);
        String[] orgIds = organizationQuery.queryOrgIdsByRoles(pkTenant, pkRoles);

        return orgIds;
    }

    /**
     * pkOrg可能存放的是租户，给orgName赋值为租户
     *
     * @param objects
     */
    private void setOrgName(Object[] objects) throws BusinessException {
        if (ArrayUtils.isEmpty(objects))
            return;

        for (Object vo : objects) {
            if (BeanHelper.getProperty(vo, ProjectVO.ORG_NAME) == null
                    && BeanHelper.getProperty(vo, ProjectVO.PK_ORG) != null) {
                TenantInfo tenantInfo = tenantInfoQuery.queryTenantInfoById(BeanHelper.getProperty(vo, ProjectVO.PK_ORG).toString());
                if (tenantInfo != null) {
                    BeanHelper.setProperty(vo, ProjectVO.ORG_NAME, tenantInfo.getTenantName());
                }
            }
        }
    }

    @GetMapping(value = "/{id}")
    @ResponseBody
    public ProjectViewVO query(@PathVariable String id)
            throws BusinessException {
        ProjectViewVO projectViewVO = query.queryProjectViewVO(id);

        if (projectViewVO == null) {
            return null;
        }
        // 判断组织名称是否为空
        if (StringUtils.isEmpty(projectViewVO.getOrgName()) && StringUtils.isNotEmpty(projectViewVO.getPkOrg())) {
            // 未跟nc集成，pkOrg存的是租户
            TenantInfo tenantInfo = tenantInfoQuery.queryTenantInfoById(projectViewVO.getPkOrg());
            if (tenantInfo != null) {
                projectViewVO.setOrgName(tenantInfo.getTenantName());
            }
        }

        userInfoQuery.tranUserInfoField(new ProjectViewVO[]{projectViewVO},
                USER_ID_FIELDS, USER_NAME_FIELDS);

        if (ProjectConst.NCUSERDEFAULTID.equals(projectViewVO.getCreator()))
            projectViewVO.setCreatorName(ProjectConst.NCUSERDEFAULTINAME);

        if(isUseNewTeam()){
            fillEntAndAddMemberInfoByNewVersion(projectViewVO);
        }else{
            fillEntAndMemberInfoField(projectViewVO);
        }
        return projectViewVO;
    }

    /**
     * 翻译企业名称和用户信息，信息来源为友工程人员登记
     * @param projectViewVO 项目档案
     */
    private void fillEntAndAddMemberInfoByNewVersion(ProjectViewVO projectViewVO) throws BusinessException {
        TeamEnterpriseViewVO[] teamEnterpriseViewVOs = projectViewVO.getTeamEnterpriseViewVOs();
        if(teamEnterpriseViewVOs == null || teamEnterpriseViewVOs.length <= 0){
            return;
        }

        List<String> pkEnterpriseList = new ArrayList<>();
        List<String> userIdList = new ArrayList<>();
        for(TeamEnterpriseViewVO teamEnterpriseVO : teamEnterpriseViewVOs){
            pkEnterpriseList.add(teamEnterpriseVO.getPkEnterprise());
            TeamMemberViewVO[] teamMemberViewVOS = teamEnterpriseVO.getTeamMemberViewVOs();
            if(teamMemberViewVOS != null && teamMemberViewVOS.length > 0){
                for(TeamMemberViewVO teamMemberViewVO : teamMemberViewVOS){
                    userIdList.add(teamMemberViewVO.getPkUser());
                }
            }
        }

        // 查询企业信息
        Map<String, EnterpriseVO> pkEnterpriseMap = new HashMap<>();
        if(pkEnterpriseList.size() > 0){
            EnterpriseVO[] enterpriseVOS = enterpriseQuery.queryByIds(pkEnterpriseList.toArray(new String[]{}));
            if(enterpriseVOS != null && enterpriseVOS.length > 0){
                for(EnterpriseVO enterpriseVO : enterpriseVOS){
                    pkEnterpriseMap.put(enterpriseVO.getPkEnterprise(), enterpriseVO);
                }
            }
        }

        // 查询人员信息
        Map<String, PersonnelVO> personnelVOMap = new HashMap<>();
        if(userIdList.size() > 0){
            PersonnelVO[] personnelVOS = personnelQuery.queryByUserIds(userIdList.toArray(new String[]{}));
            if(personnelVOS != null && personnelVOS.length > 0){
                for(PersonnelVO personnelVO : personnelVOS){
                    personnelVOMap.put(personnelVO.getUserId(), personnelVO);
                }
            }
        }

        EnterpriseVO managerEnterpriseVO = pkEnterpriseMap.get(projectViewVO.getManager());
        if(managerEnterpriseVO != null){
            projectViewVO.setManagerEnt(managerEnterpriseVO.getName());
        }

        // 翻译企业名称和人员信息
        for(TeamEnterpriseViewVO enterpriseViewVO : teamEnterpriseViewVOs){
            EnterpriseVO enterpriseVO = pkEnterpriseMap.get(enterpriseViewVO.getPkEnterprise());
            if(enterpriseVO == null){
                continue;
            }

            enterpriseViewVO.setEnterpriseName(enterpriseVO.getName());
            TeamMemberViewVO[] teamMemberViewVOS = enterpriseViewVO.getTeamMemberViewVOs();
            if(teamMemberViewVOS != null && teamMemberViewVOS.length > 0){
                for(TeamMemberViewVO teamMemberViewVO : teamMemberViewVOS){
                    teamMemberViewVO.setEnterpriseName(enterpriseVO.getName());

                    PersonnelVO personnelVO = personnelVOMap.get(teamMemberViewVO.getPkUser());
                    if(personnelVO == null){
                        continue;
                    }
                    teamMemberViewVO.setUserName(personnelVO.getSname());
                    teamMemberViewVO.setPhoneNo(personnelVO.getPhone());
                    teamMemberViewVO.setEmail(personnelVO.getEmail());
                }
            }
        }

    }

    /**
     * 补全参与企业、参与人员必要的展示信息
     *
     * @param projectViewVO
     */
    private void fillEntAndMemberInfoField(ProjectViewVO projectViewVO) {
        TeamEnterpriseViewVO[] teamEnterpriseViewVOs = projectViewVO.getTeamEnterpriseViewVOs();
        TeamMemberViewVO[] teamMemberViewVOs = new TeamMemberViewVO[]{};
                    TeamMemberViewVO[] tempMemberViewVOs;
                    if (ArrayUtils.isNotEmpty(teamEnterpriseViewVOs)) {
                        enterpriseInfoQuery.tranEntInfoField(teamEnterpriseViewVOs, new String[]{TeamEnterpriseVO.PK_ENTERPRISE}, new String[]{TeamEnterpriseVO.ENTERPRISE_NAME});
                        for (TeamEnterpriseViewVO teamEnterpriseViewVO : teamEnterpriseViewVOs) {
                            tempMemberViewVOs = teamEnterpriseViewVO.getTeamMemberViewVOs();
                            if (ArrayUtils.isNotEmpty(tempMemberViewVOs)) {
                                teamMemberViewVOs = ArrayUtils.addAll(teamMemberViewVOs, tempMemberViewVOs);
                }
            }
        }
        if (ArrayUtils.isNotEmpty(teamMemberViewVOs)) {
            enterpriseInfoQuery.tranEntInfoField(teamMemberViewVOs, new String[]{TeamMemberVO.PK_ENTERPRISE}, new String[]{TeamMemberVO.ENTERPRISE_NAME});
            userInfoAdd(teamMemberViewVOs);

            Map<String, List<TeamMemberViewVO>> pkEnterAndMemberMap = getPkEnterAndMemberViewMap(teamMemberViewVOs);

            List<TeamMemberViewVO> teamMemberViewVOList = new ArrayList<TeamMemberViewVO>();
            for (TeamEnterpriseViewVO teamEnterpriseViewVO : teamEnterpriseViewVOs) {
                teamMemberViewVOList = pkEnterAndMemberMap.get(teamEnterpriseViewVO.getPkEnterprise());
                if (teamMemberViewVOList != null && teamMemberViewVOList.size() > 0) {
                    teamEnterpriseViewVO.setTeamMemberViewVOs(teamMemberViewVOList.toArray(new TeamMemberViewVO[0]));
                }
            }
        }

        projectViewVO.setTeamEnterpriseViewVOs(teamEnterpriseViewVOs);
    }


    private Map<String, List<TeamMemberViewVO>> getPkEnterAndMemberViewMap(TeamMemberViewVO[] teamMemberViewVOs) {
        Map<String, List<TeamMemberViewVO>> pkEnterAndMemberMap = new HashMap<String, List<TeamMemberViewVO>>();
        String tempPkEnter;
        for (TeamMemberViewVO teamMemberViewVO : teamMemberViewVOs) {
            tempPkEnter = teamMemberViewVO.getPkEnterprise();
            if (pkEnterAndMemberMap.get(tempPkEnter) == null) {
                List<TeamMemberViewVO> teamMemberViewVOList = new ArrayList<TeamMemberViewVO>();
                teamMemberViewVOList.add(teamMemberViewVO);
                pkEnterAndMemberMap.put(tempPkEnter, teamMemberViewVOList);
            } else {
                pkEnterAndMemberMap.get(tempPkEnter).add(teamMemberViewVO);
            }
        }
        return pkEnterAndMemberMap;
    }

    private void userInfoAdd(TeamMemberViewVO[] teamMemberViewVOs) {
        if (ArrayUtils.isEmpty(teamMemberViewVOs)) {
            return;
        }
        Map<String, UserInfo> users = userInfoQuery.extractUserInfoFromBeans(teamMemberViewVOs, new String[]{TeamMemberVO.PK_USER});
        for (TeamMemberViewVO member : teamMemberViewVOs) {
            UserInfo user = users.get(member.getPkUser());
            if (user == null) {
                continue;
            }
            member.setUserName(user.getUserName());
            member.setEmail(user.getUserEmail());
            member.setPhoneNo(user.getUserMobile());
        }

        Arrays.sort(teamMemberViewVOs, new Comparator<TeamMemberViewVO>() {
            @Override
            public int compare(TeamMemberViewVO o1, TeamMemberViewVO o2) {
                if (o1 == o2) {
                    return 0;
                }
                if (o1 == null) {
                    return 1;
                }
                if (o2 == null) {
                    return -1;
                }

                return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());

            }
        });

    }

    @PostMapping(value = "/insert")
    @ResponseBody
    public ProjectViewVO insert(@RequestBody @Validated(ProjectViewVO.InsertValid.class) ProjectViewVO projectViewVO,
                                BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        projectViewVO.setSname(StringUtils.trim(projectViewVO.getSname()));
        // 校验名称和编码的合法性
        if (CodeNameUtils.checkCodeStr(projectViewVO.getScode()) >= 0 || CodeNameUtils.checkNameStr(projectViewVO.getSname(), null) >= 0) {
            throw new IllegalRequestArgException();
        }

        checkEntAndMember(projectViewVO);

        projectViewVO.setPkTenant(RuntimeEnvironment.getTenantId());

        projectViewVO = maintain.insert(projectViewVO);

        //通过项目档案自动生成项目计划(捕获异常不影响主业务逻辑)
//        try {
//            autoGenerationProjectPlan(projectViewVO);
//        } catch (BusinessException e) {
//            log.error("自动关联新增计划模板失败"+e.getMessage());
//            log.error("失败url:/project/insert  :" + projectViewVO);
//        }

        return projectViewVO;
    }

    /**
     * 关联计划模板自动生成项目计划（内部调用 注：目前因为没有类型 是关联不到计划模板的，但逻辑暂时加上）
     *
     * @param projectViewVO
     * @throws BusinessException
     */
    private void autoGenerationProjectPlan(@Validated(ProjectViewVO.InsertValid.class) @RequestBody ProjectViewVO projectViewVO) throws BusinessException {
        //1.匹配到的模板总数
        List<PlanTempletVO> planTempletVOs = queryPlanTemplate(projectViewVO);
        //2.生成计划
        if (null != planTempletVOs && planTempletVOs.size() > 0) {
            for (PlanTempletVO rootNode : planTempletVOs) {
                //计划容器
                ProjectPlanVO temp = new ProjectPlanVO();

                Map<String, String> planMap = new HashMap<>();
                buildPlan(rootNode, temp, planMap);
                //默认审核通过(生效)在在server端更改，在这里做会被覆盖

                //保存
                projectPlanMaintain.autoSavePlan(temp);
            }
        }
    }

    private List<PlanTempletVO> queryPlanTemplate(@Validated(ProjectViewVO.InsertValid.class) @RequestBody ProjectViewVO projectViewVO) throws BusinessException {
        PlanTempletVO[] templetVOS = planTempletService.autoSearchPlanTemp(RuntimeEnvironment.getTenantId(), projectViewVO.getPkOrg(), projectViewVO.getPkProjectType());
        if (templetVOS == null || templetVOS.length == 0) return new ArrayList();
        Map<String, List<PlanTempletVO>> childMap = genChildMap(templetVOS);
        return childMap.get(StringUtils.EMPTY);
    }

    private void buildPlan(PlanTempletVO tempVO, ProjectPlanVO planVO, Map<String, String> planMap) throws BusinessException {
        if (tempVO.getChildren() != null) {
            for (PlanTempletVO vo : tempVO.getChildren()) {
                ProjectPlanVO pro = new ProjectPlanVO();
                convert(planVO, pro, vo, planMap);
                buildPlan(vo, pro, planMap);
            }
        }
    }

    private void convert(ProjectPlanVO parent, ProjectPlanVO child, PlanTempletVO tempVO, Map<String, String> planMap) throws BusinessException {
        //设置上级计划childCount
        int childCount = parent.getChildCount() == null ? 0 : parent.getChildCount();
        parent.setChildCount(childCount + 1);
        //构建子计划
        child.setPkProject(parent.getPkProject());
        child.setSname(tempVO.getSname());
        if (StringUtils.isBlank(parent.getScode()) || parent.getScode().equals("0")) {
            child.setScode(parent.getChildCount().toString());
        } else {
            child.setScode(parent.getScode() + "." + parent.getChildCount());
        }
        child.setSeq(parent.getChildCount());
        if (tempVO.getExpectDuration() != null) {
            child.setExpeDuration(tempVO.getExpectDuration());
            child.setExpeStartDate(formatDate(new Date()));
            child.setExpeEndDate(formatDate(org.apache.commons.lang3.time.DateUtils.addDays(new Date(), tempVO.getExpectDuration() - 1)));
        } else {
            child.setExpeDuration(1);
            child.setExpeStartDate(formatDate(new Date()));
            child.setExpeEndDate(formatDate(new Date()));
        }

        child.setRelatedBillType(tempVO.getRelatedBillType());
        child.setManager(tempVO.getManager());
        child.setManagerName(tempVO.getManagerName());
        child.setPkMilestone(tempVO.getPkMilestone());
        child.setMilestoneName(tempVO.getMilestoneName());
        child.setRelatedBillType(tempVO.getRelatedBillType());
        child.setRelatedBillTypeName(tempVO.getRelatedBillTypeName());
        child.setPkDepartment(tempVO.getPkDepartment());
        child.setDepartmentName(tempVO.getDepartmentName());

        planMap.put(tempVO.getPkPlanTemplet(), child.getScode());
        child.setDependPlanName(tempVO.getDependTemplet());

        ProjectPlanVO[] childs = parent.getChildren();
        if (childs == null) childs = new ProjectPlanVO[0];
        parent.setChildren(ArrayUtils.add(childs, child));

    }

    private Date formatDate(Date date) {
        if (date != null) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String dateStr = sdf.format(date);
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private Map<String, List<PlanTempletVO>> genChildMap(PlanTempletVO[] allVOs) {
        // 构造树
        Map<String, List<PlanTempletVO>> childMap = new HashMap<>();
        for (PlanTempletVO vo : allVOs) {
            vo.setKey(vo.getPkPlanTemplet());
            String parent = vo.getPkParent();
            if (StringUtils.isEmpty(parent)) {
                parent = StringUtils.EMPTY;
            }
            List<PlanTempletVO> children = childMap.get(parent);
            if (children == null) {
                children = new ArrayList<>();
                childMap.put(parent, children);
            }
            children.add(vo);
        }
        for (PlanTempletVO vo : allVOs) {
            List<PlanTempletVO> children = childMap.get(vo.getPkPlanTemplet());
            if (children != null) {
                vo.setChildren(children.toArray(new PlanTempletVO[0]));
            }
        }
        return childMap;
    }


    /**
     * 项目参与方与项目团队成员相关校验
     */
    private void checkEntAndMember(ProjectViewVO projectViewVO) throws BusinessException {
        String managerEnt = projectViewVO.getManagerEnt();
        TeamEnterpriseViewVO[] entViewVOs = projectViewVO.getTeamEnterpriseViewVOs();

        if (ArrayUtils.isEmpty(entViewVOs))
            return;

        Map<String, TeamEnterpriseViewVO> pkEntMap = new HashMap<>();

        for (TeamEnterpriseViewVO entViewVO : entViewVOs) {
            String pkEnt = entViewVO.getPkEnterprise();

            if (StringUtils.isEmpty(pkEnt))
                throw new IllegalRequestArgException();

            if (pkEntMap.get(pkEnt) != null){
                throw new BusinessException("项目参与方重复");
            }

            pkEntMap.put(pkEnt, entViewVO);
        }


        if (StringUtils.isEmpty(projectViewVO.getManager()) && StringUtils.isEmpty(managerEnt))
            return;

        if (!pkEntMap.containsKey(managerEnt)) {
            throw new BusinessException("项目经理所属企业未加入项目参与方");
        }

        TeamEnterpriseViewVO teamEnterpriseViewVO = pkEntMap.get(managerEnt);
        TeamMemberViewVO[] teamMemberViewVOs = teamEnterpriseViewVO.getTeamMemberViewVOs();

        if (ArrayUtils.isEmpty(teamMemberViewVOs)){
            throw new BusinessException("项目经理未加入项目团队");
        }

        boolean flag = false;
        for (TeamMemberViewVO memViewVO : teamMemberViewVOs) {
            if (projectViewVO.getManager().equals(memViewVO.getPkUser())) {
                flag = true;
                break;
            }
        }

        if (!flag){
            throw new BusinessException("项目经理未加入项目团队");
        }
    }


    @PostMapping(value = "/update")
    @ResponseBody
    public ProjectViewVO update(@RequestBody ProjectUpdateViewVO projectUpdateViewVO) throws BusinessException {
        checkBeforeUpdate(projectUpdateViewVO);
        String pkProject = maintain.updateProjectInfo(projectUpdateViewVO);
        return this.query(pkProject);
    }

    private void checkBeforeUpdate(ProjectUpdateViewVO projectUpdateViewVO) throws BusinessException {
        ProjectVO projectVO = projectUpdateViewVO.getProject();
        String sname = projectVO.getSname();
        if (StringUtils.isEmpty(sname)) {
            throw new BusinessException("项目名称不能为空");
        }
        String scode = projectVO.getScode();
        if (StringUtils.isEmpty(scode)) {
            throw new BusinessException("项目编码不能为空");
        }
    }

    @PostMapping(value = "/delete")
    @ResponseBody
    public ProjectVO delete(@RequestBody ProjectVO project, BindingResult errors) throws BusinessException {
        if (StringUtils.isEmpty(project.getPkProject())) {
            errors.rejectValue(ProjectVO.PK_PROJECT, null);
        }
        if (StringUtils.isEmpty(project.getChangeFlag())) {
            errors.rejectValue(CommonFieldConst.CHANGE_FLAG, null);
        }
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        String pk = maintain.delete(project.getPkProject(), project.getChangeFlag(),
                RuntimeEnvironment.getLoginUserId());
        return project;
    }

    @PostMapping(value = "/end")
    @ResponseBody
    public ProjectVO end(@RequestBody @Validated ProjectVO project, BindingResult errors) throws BusinessException {
        if (StringUtils.isEmpty(project.getPkProject())) {
            errors.rejectValue(ProjectVO.PK_PROJECT, null);
        }
        if (project.getEndDate() == null) {
            errors.rejectValue(ProjectVO.END_DATE, null);
        }
        if (StringUtils.isEmpty(project.getChangeFlag())) {
            errors.rejectValue(CommonFieldConst.CHANGE_FLAG, null);
        }

        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        String pk = maintain.updateEnd(project.getPkProject(),
                project.getChangeFlag(), project.getEndDate(), RuntimeEnvironment.getLoginUserId(), project.getDescription());
        return project;
    }

    @RequestMapping(value = "/queryManager")
    @ResponseBody
    public UserSearchResultVO.ContentVO queryManager(String keyword, Integer pageSize, Integer pageNum) throws BusinessException {

        if (pageNum == null || pageNum < 0) {
            pageNum = 0;
        }
        // TODO 先写死成500
        if (pageSize == null || pageSize < 0 || pageSize > 500) {
            pageSize = 500;
        }

        String pkTenanat = RuntimeEnvironment.getTenantId();

        UserSearchResultVO.ContentVO resultVO = userInfoQuery.searchUserInSystem(pkTenanat, keyword, pageNum, pageSize, new String[]{});

        if (resultVO.getContent() != null) {
            String[] userids = new String[resultVO.getContent().length];

            Arrays.sort(resultVO.getContent(), new Comparator<UserInfo>() {
                @Override
                public int compare(UserInfo o1, UserInfo o2) {
                    if (o1 == o2) {
                        return 0;
                    }
                    if (o1 == null) {
                        return 1;
                    }
                    if (o2 == null) {
                        return -1;
                    }

                    return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());

                }
            });

            for (int i = 0; i < resultVO.getContent().length; i++) {
                userids[i] = resultVO.getContent()[i].getUserId();
            }

            Map<String, EnterpriseInfo[]> entUserMap;

            if (isUseNewTeam()) {
                entUserMap = getNewTeamEnterpriseByUserIds(userids);
            } else {
                entUserMap = enterpriseInfoQuery.getEnterprisesOfUsers(userids);
            }


            List<UserInfo> userInfoList = new ArrayList<UserInfo>();

            for (UserInfo userInfo : resultVO.getContent()) {

                EnterpriseInfo[] entInfos = entUserMap.get(userInfo.getUserId());
                if (ArrayUtils.isNotEmpty(entInfos)) {
                    try {
                        for (EnterpriseInfo entInfo : entInfos) {
                            UserInfo finalUserInfo = (UserInfo) userInfo.clone();
                            finalUserInfo.setDefaultEntId(entInfo.getId());
                            finalUserInfo.setDefaultEntName(entInfo.getName());
                            finalUserInfo.setDefaultRole(entInfo.getRole());
                            userInfoList.add(finalUserInfo);
                        }
                    } catch (CloneNotSupportedException e) {
                        log.error(e.getMessage());
                    }

                }
            }

            if (userInfoList != null && userInfoList.size() > 0) {
                resultVO.setContent(userInfoList.toArray(new UserInfo[0]));
            } else {
                resultVO.setContent(new UserInfo[0]);
            }

        }

        return resultVO;


    }

    private Map<String, EnterpriseInfo[]> getNewTeamEnterpriseByUserIds(String[] userIds) throws BusinessException {
        Map<String, EnterpriseVO[]> enterpriseMap = enterpriseQuery.queryByUserIds(userIds);

        Map<String, EnterpriseInfo[]> result = new HashMap<>();

        if(enterpriseMap.size() <= 0){
            return result;
        }
        for(Map.Entry<String, EnterpriseVO[]> entry : enterpriseMap.entrySet()){
            EnterpriseVO[] enterpriseVOS = entry.getValue();
            if(enterpriseVOS == null || enterpriseVOS.length <= 0){
                continue;
            }

            EnterpriseInfo[] enterpriseInfoArray = new EnterpriseInfo[enterpriseVOS.length];

            for(int i = 0; i < enterpriseVOS.length; i++){
                EnterpriseInfo enterpriseInfo = new EnterpriseInfo();
                EnterpriseVO enterpriseVO = enterpriseVOS[i];
                enterpriseInfo.setId(enterpriseVO.getPkEnterprise());
                enterpriseInfo.setName(enterpriseVO.getName());
                enterpriseInfo.setRole(enterpriseVO.getRole());
                enterpriseInfoArray[i] = enterpriseInfo;
            }

            result.put(entry.getKey(), enterpriseInfoArray);

        }
        return result;
    }

    @GetMapping(value = "/queryBySrc")
    @ResponseBody
    public ProjectViewVO queryBySrc(String pkSrc)
            throws BusinessException {
        String tenantId = RuntimeEnvironment.getTenantId();
        if (StringUtils.isEmpty(tenantId))
            throw new BusinessException("未找到对应租户信息");

        ProjectViewVO projectViewVO = query.queryProjectViewVOByPkSrc(tenantId, pkSrc);
        if (projectViewVO == null) {
            return null;
        }
        userInfoQuery.tranUserInfoField(new ProjectViewVO[]{projectViewVO},
                USER_ID_FIELDS, USER_NAME_FIELDS);

        fillEntAndMemberInfoField(projectViewVO);

        return projectViewVO;
    }
}
